package com.sx.gateway.filter;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * @author shengx
 * @date 2020/5/16 20:28
 */
public class TokenGlobalFilter implements GlobalFilter, Ordered {
    private String[] skipAuthUrls = {"/api/user/", "/api/code/"};

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getURI().getPath();
        System.out.println("url:" + url);
        if (null != skipAuthUrls) {
            for (String skipAuthUrl : skipAuthUrls) {
                if (url.contains(skipAuthUrl))
                    return chain.filter(exchange);
            }
        }

        List<HttpCookie> cookies = exchange.getRequest().getCookies().get("token");
        ServerHttpResponse response = exchange.getResponse();
        System.out.println(cookies);
        if (cookies != null && cookies.size() > 0) {
            String token = cookies.get(0).getValue();
            try {
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("123456789".getBytes())).build();
                DecodedJWT verify = jwtVerifier.verify(token);
//                System.out.println(verify.getHeader());
                return chain.filter(exchange);
            } catch (Exception e) {
                e.printStackTrace();
                return authErro(response, "认证失败");
            }

        }
        return authErro(response, "未认证");
    }

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 认证错误输出
     *
     * @param resp 响应对象
     * @param mess 错误信息
     * @return
     */
    private Mono<Void> authErro(ServerHttpResponse resp, String mess) {
        resp.setStatusCode(HttpStatus.UNAUTHORIZED);
        resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        String returnStr = mess;
        DataBuffer buffer = resp.bufferFactory().wrap(returnStr.getBytes(StandardCharsets.UTF_8));
        return resp.writeWith(Flux.just(buffer));
    }
}
